import type { H3Event } from 'h3';
import { z } from 'zod';

/**
 * 校验请求体数据
 * @param event H3Event 对象
 * @param schema Zod 校验模式
 * @returns 校验后的数据
 */
export async function validateBody<T>(event: H3Event, schema: z.ZodSchema<T>): Promise<T> {
  try {
    const body = await readBody(event);
    return schema.parse(body);
  }
  catch (error) {
    if (error instanceof z.ZodError) {
      const errorMessages = error.errors.map((err) => {
        const path = err.path.join('.');
        return path ? `${path}: ${err.message}` : err.message;
      });

      throw createError({
        statusCode: 400,
        statusMessage: `数据校验失败: ${errorMessages.join(', ')}`,
      });
    }
    throw error;
  }
}

/**
 * 校验查询参数
 * @param event H3Event 对象
 * @param schema Zod 校验模式
 * @returns 校验后的查询参数
 */
export function validateQuery<T>(event: H3Event, schema: z.ZodSchema<T>): T {
  try {
    const query = getQuery(event);
    return schema.parse(query);
  }
  catch (error) {
    if (error instanceof z.ZodError) {
      const errorMessages = error.errors.map((err) => {
        const path = err.path.join('.');
        return path ? `${path}: ${err.message}` : err.message;
      });

      throw createError({
        statusCode: 400,
        statusMessage: `查询参数校验失败: ${errorMessages.join(', ')}`,
      });
    }
    throw error;
  }
}

/**
 * 校验路由参数
 * @param event H3Event 对象
 * @param schema Zod 校验模式
 * @param paramName 参数名称
 * @returns 校验后的参数值
 */
export function validateParam<T>(event: H3Event, schema: z.ZodSchema<T>, paramName: string): T {
  try {
    const param = getRouterParam(event, paramName);
    return schema.parse(param);
  }
  catch (error) {
    if (error instanceof z.ZodError) {
      const errorMessages = error.errors.map(err => err.message);

      throw createError({
        statusCode: 400,
        statusMessage: `路由参数 ${paramName} 校验失败: ${errorMessages.join(', ')}`,
      });
    }
    throw error;
  }
}

/**
 * 通用数据校验函数
 * @param data 要校验的数据
 * @param schema Zod 校验模式
 * @param errorPrefix 错误信息前缀
 * @returns 校验后的数据
 */
export function validateData<T>(data: unknown, schema: z.ZodSchema<T>, errorPrefix: string = '数据校验失败'): T {
  try {
    return schema.parse(data);
  }
  catch (error) {
    if (error instanceof z.ZodError) {
      const errorMessages = error.errors.map((err) => {
        const path = err.path.join('.');
        return path ? `${path}: ${err.message}` : err.message;
      });

      throw createError({
        statusCode: 400,
        statusMessage: `${errorPrefix}: ${errorMessages.join(', ')}`,
      });
    }
    throw error;
  }
}

/**
 * 安全解析数据（不抛出错误）
 * @param data 要解析的数据
 * @param schema Zod 校验模式
 * @returns 解析结果
 */
export function safeParseData<T>(data: unknown, schema: z.ZodSchema<T>) {
  return schema.safeParse(data);
}
